package com.easyoffer.common.util;

import cn.hutool.bloomfilter.BitMapBloomFilter;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.setting.yaml.YamlUtil;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.ConfigType;
import com.alibaba.nacos.api.exception.NacosException;
import com.easyoffer.common.ErrorCode;
import com.easyoffer.exception.BusinessException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.core.ApplicationContext;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.yaml.snakeyaml.Yaml;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
@Slf4j
public class BlackIpUtil {
    private static List<String> blackIpList = new ArrayList<>();
    private static BitMapBloomFilter bloomFilter;
    private static String dataId;
    private static String group;

    @Value("${nacos.black-list.data-id}")
    public void setDataId(String dataId) {
        BlackIpUtil.dataId = dataId;
    }
    @Value("${nacos.black-list.group}")
    public void setGroup(String group) {
        BlackIpUtil.group = group;
    }

    //添加封禁ip
    public static void addBlackIp(String applicationName,String ip, HttpServletRequest request) {
        if (StringUtils.isBlank(ip))
            throw new BusinessException(ErrorCode.OPERATION_ERROR,"ip不能为空");
        blackIpList.add(ip);
        bloomFilter.add(ip);
        // 获取 ServletContext
        ServletContext servletContext = request.getServletContext();
        // 通过 WebApplicationContextUtils 获取 WebApplicationContext
        WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        if (applicationContext != null) {
            ConfigService configService = applicationContext.getBean(ConfigService.class);
            Yaml yaml = new Yaml();
            Map<String, Object> map = new HashMap<>();
            map.put(applicationName, Map.of("black-list", blackIpList));
            String blackIpListYaml = yaml.dump(map);
            try {
                configService.publishConfig(dataId, group, blackIpListYaml, ConfigType.YAML.getType());
            } catch (NacosException e) {
                log.error("发布ip黑名单至nacos失败");
                throw new RuntimeException(e);
            }
        }else {
            log.error("ApplicationContext 获取失败,已将黑名单ip添加至blackIpList 并且更新bloomFilter,请尽快处理上传配置问题");
        }


    }

    // 判断 ip 是否在黑名单内
    public static boolean isBlackIp(String ip) {
        return bloomFilter.contains(ip);
    }

    // 重建 ip 黑名单
    public static void rebuildBlackIp(String configInfo) {
        if (StrUtil.isBlank(configInfo)) {
            configInfo = "{}";
        }
        // 解析 yaml 文件
        Yaml yaml = new Yaml();
        Map map = yaml.loadAs(configInfo, Map.class);
        // 获取 ip 黑名单
        if (map == null || map.isEmpty()) {
            log.error("黑名单配置文件解析失败");
            return;
        }
        Map<String, Object> easyOfferMap = ((Map) map.get("easy-offer"));
        blackIpList = (List<String>) easyOfferMap.get("black-list");
        // 加锁防止并发
        synchronized (BlackIpUtil.class) {
            if (CollectionUtil.isNotEmpty(blackIpList)) {
                // 注意构造参数的设置
                BitMapBloomFilter bitMapBloomFilter = new BitMapBloomFilter(100);
                for (String ip : blackIpList) {
                    bitMapBloomFilter.add(ip);
                }
                bloomFilter = bitMapBloomFilter;
            } else {
                bloomFilter = new BitMapBloomFilter(100);
            }
        }
    }
}
